package com.hzyl.famousreader.view.widget.core.loader;

import android.Manifest;
import android.support.annotation.Nullable;
import com.blankj.utilcode.util.*;
import com.hzyl.famousreader.view.widget.core.Charset;
import com.hzyl.famousreader.view.widget.core.CharsetUtils;
import com.hzyl.famousreader.view.widget.core.PageView;
import com.hzyl.famousreader.view.widget.core.model.Chapter;
import com.hzyl.famousreader.view.widget.core.model.Page;

import java.io.*;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 书籍加载器基类
 */
public abstract class LoaderAbs {

  private PageView mView;

  private int curChapterPos = 0;

  private int curChapterPagePos = 0;

  private static final int DEFAULT_MARGIN_HEIGHT = 28;
  private static final int DEFAULT_MARGIN_WIDTH = 12;

  //书籍绘制区域的宽高
  private int mVisibleWidth;
  private int mVisibleHeight;
  //应用的宽高
  private int mDisplayWidth;
  private int mDisplayHeight;
  //间距
  private int mMarginWidth = ConvertUtils.dp2px(DEFAULT_MARGIN_WIDTH);
  private int mMarginHeight = ConvertUtils.dp2px(DEFAULT_MARGIN_HEIGHT);

  //默认从文件中获取数据的长度
  private final static int BUFFER_SIZE = 512 * 1024;
  //没有标题的时候，每个章节的最大长度
  private final static int MAX_LENGTH_WITH_NO_CHAPTER = 10 * 1024;

  // "序(章)|前言"
  private final static Pattern mPreChapterPattern = Pattern.compile("^(\\s{0,10})((\u5e8f[\u7ae0\u8a00]?)|(\u524d\u8a00)|(\u6954\u5b50))(\\s{0,10})$", Pattern.MULTILINE);

  //正则表达式章节匹配模式
  // "(第)([0-9零一二两三四五六七八九十百千万壹贰叁肆伍陆柒捌玖拾佰仟]{1,10})([章节回集卷])(.*)"
  private static final String[] CHAPTER_PATTERNS = new String[]{
    "^(.{0,8})(\u7b2c)([0-9\u96f6\u4e00\u4e8c\u4e24\u4e09\u56db\u4e94\u516d\u4e03\u516b\u4e5d\u5341\u767e\u5343\u4e07\u58f9\u8d30\u53c1\u8086\u4f0d\u9646\u67d2\u634c\u7396\u62fe\u4f70\u4edf]{1,10})([\u7ae0\u8282\u56de\u96c6\u5377])(.{0,30})$",
    "^(\\s{0,4})([\\(\u3010\u300a]?(\u5377)?)([0-9\u96f6\u4e00\u4e8c\u4e24\u4e09\u56db\u4e94\u516d\u4e03\u516b\u4e5d\u5341\u767e\u5343\u4e07\u58f9\u8d30\u53c1\u8086\u4f0d\u9646\u67d2\u634c\u7396\u62fe\u4f70\u4edf]{1,10})([\\.:\uff1a\u0020\f\t])(.{0,30})$",
    "^(\\s{0,4})([\\(\uff08\u3010\u300a])(.{0,30})([\\)\uff09\u3011\u300b])(\\s{0,2})$",
    "^(\\s{0,4})(\u6b63\u6587)(.{0,20})$",
    "^(.{0,4})(BookChapter|chapter)(\\s{0,4})([0-9]{1,4})(.{0,30})$"};

  //上一章的记录
  private int mLastChapter = 0;

  //章节解析模式
  private Pattern mChapterPattern = null;

  //编码类型
  private Charset mCharset;

  //页面加载状态
  protected DataLoaderStatusEnum curLoadStatus = DataLoaderStatusEnum.LOADING;

  private File bookFile;

  ////////////////////////////////////////////////////////
  // 书页信息
  ////////////////////////////////////////////////////////
  /**
   * 当前章节列表
   */
  private List<Chapter> chapters;

  /**
   * 当前显示的页
   */
  private Page curPage;

  /**
   * 上一章的页面列表缓存
   */
  private WeakReference<List<Page>> mWeakPrePageList;

  /**
   * 当前章节的页面列表
   */
  private List<Page> curPages;

  /**
   * 下一章的页面列表缓存
   */
  private List<Page> nextPages;

  //被遮盖的页，或者认为被取消显示的页
  private Page mCancelPage;

  private String path;

  private OnPageChangeListener listener;

  public LoaderAbs(PageView mView) {
    this.mView = mView;
  }

  public void setPath(String path) {
    this.path = path;
  }

  //参数改变，重新加载数据
  public void reload() {
    //取消缓存
    mWeakPrePageList = null;
    nextPages = null;
    //如果当前为完成状态。
    if (curLoadStatus == DataLoaderStatusEnum.FINISH) {
      //重新计算页面
      curPages = loadPages(curChapterPos);

      //防止在最后一页，通过修改字体，以至于页面数减少导致崩溃的问题
      if (curPage.getPosition() >= curPages.size()) {
        curPage.setPosition(curPages.size() - 1);
      }
    }
    //重新设置文章指针的位置
    curPage = getCurPage(curPage.getPosition());
  }

  public List<Chapter> getChapters() {
    return chapters;
  }

  /**
   * 获取加载状态
   *
   * @return
   */
  public DataLoaderStatusEnum getLoadStatus() {
    return curLoadStatus;
  }

  /**
   * 当前章节的标题
   */
  public String getChapterTitle() {
    return chapters.get(curChapterPos).getTitle();
  }

  /**
   * 当前书页在该章节中的位置
   */
  public int getCurPagePosition() {
    return curPage.getPosition() + 1;
  }

  /**
   * 当前章节的页数
   */
  public int getCurPagesSize() {
    return curPages.size();
  }

  /**
   * 当前页
   */
  public Page getCurPage() {
    return curPage;
  }

  public void setCurChapterPos(int curChapterPos) {
    this.curChapterPos = curChapterPos;
  }

  public void setCurChapterPagePos(int curChapterPagePos) {
    this.curChapterPagePos = curChapterPagePos;
  }

  /**
   * 跳转到上一章
   */
  public boolean prevChapter() {
    boolean canPrev = loadPrevChapter();
    if (canPrev) {
      curPage = getCurPage(0);
      invokePageChangeListener();
    }
    return canPrev;
  }

  /**
   * 跳转到下一章
   */
  public boolean nextChapter() {
    boolean canNext = loadNextChapter();
    if (canNext) {
      curPage = getCurPage(0);
      invokePageChangeListener();
    }
    return canNext;
  }

  /**
   * 跳转到指定章节
   *
   * @param pos 目标章节
   */
  public void skipToChapter(int pos) {
    //正在加载
    curLoadStatus = DataLoaderStatusEnum.LOADING;
    //绘制当前的状态
    curChapterPos = pos;
    //将上一章的缓存设置为null
    mWeakPrePageList = null;

    //将下一章缓存设置为null
    nextPages = null;

    //if (mPageChangeListener != null) {
    //  mPageChangeListener.onChapterChange(curChapterPos);
    //}

    if (curPage != null) {
      //重置position的位置，防止正在加载的时候退出时候存储的位置为上一章的页码
      curPage.setPosition(0);
    }

    openBook();

    invokePageChangeListener();
  }

  /**
   * 跳转到上一页
   *
   * @return true-可以往前翻，false-第一页
   */
  public boolean prevPage() {
    if (!checkStatus()) return false;

    //判断是否达到章节的起始点
    Page prevPage = getPrevPage();
    if (prevPage == null) {
      //载入上一章。

      if (!loadPrevChapter()) {
        return false;
      } else {
        mCancelPage = curPage;
        curPage = curPages.get(curPages.size() - 1);
        return true;
      }
    }

    mCancelPage = curPage;
    curPage = prevPage;

    invokePageChangeListener();

    return true;
  }

  /**
   * 往后翻页
   *
   * @return true-可以往后翻，false-最后一页
   */
  public boolean nextPage() {
    if (!checkStatus()) return false;
    //判断是否到最后一页了
    Page nextPage = getNextPage();

    if (nextPage == null) {
      if (!loadNextChapter()) {
        return false;
      } else {
        mCancelPage = curPage;
        curPage = getCurPage(0);
        return true;
      }
    }

    mCancelPage = curPage;
    curPage = nextPage;

    invokePageChangeListener();

    return true;
  }

  /**
   * 当前章节跳转到具体的页
   *
   * @param pos 目标页
   */
  public void skipToPage(int pos) {
    curPage = getCurPage(pos);
    invokePageChangeListener();
  }

  public void setOnPageChangeListener(OnPageChangeListener listener) {
    this.listener = listener;
  }

  public void loadBook() {
    PermissionUtils.permission(Manifest.permission.READ_EXTERNAL_STORAGE)
      .callback(new PermissionUtils.SimpleCallback() {
        @Override
        public void onGranted() {
          bookFile = new File(path);

          if (!FileUtils.isFileExists(bookFile)) return;

          if (bookFile.length() == 0) return;

          //获取文件编码
          mCharset = CharsetUtils.getCharset(path);

          //处理本地章节的切割
          ThreadUtils.executeByIo(new ThreadUtils.Task<Object>() {
            @Nullable
            @Override
            public Object doInBackground() throws Throwable {
              loadChapter(bookFile);
              return "成功啦啦啦";
            }

            @Override
            public void onSuccess(@Nullable Object result) {
              LogUtils.d(result);
              curLoadStatus = DataLoaderStatusEnum.FINISH;
              openBook();
              mView.postInvalidate();
            }

            @Override
            public void onCancel() {
              LogUtils.d("取消啦啦啦");
            }

            @Override
            public void onFail(Throwable t) {
              LogUtils.d("失败啦啦");
              //curLoadStatus = DataLoaderStatusEnum.PARSE_ERROR;
              mView.postInvalidate();
            }
          });
        }

        @Override
        public void onDenied() {
          ToastUtils.showShort("获取权限失败！");
        }
      })
      .request();
  }

  /**
   * 适应调整视图大小
   *
   * @param w
   * @param h
   */
  public void onSizeChange(int w, int h) {
    //获取PageView的宽高
    mDisplayWidth = w;
    mDisplayHeight = h;

    //获取内容显示位置的大小
    mVisibleWidth = mDisplayWidth - mMarginWidth * 2;
    mVisibleHeight = mDisplayHeight - mMarginHeight * 2;

    //如果章节已显示，那么就重新计算页面
    if (curLoadStatus == DataLoaderStatusEnum.FINISH) {
      curPages = loadPages(curChapterPos);
      //重新设置文章指针的位置
      curPage = getCurPage(curPage.getPosition());
    }
  }

  /**
   * 打开书籍
   */
  protected void openBook() {
    curPages = loadPages(curChapterPos);
    //进行预加载
    preLoadNextChapter();
    //加载完成
    curLoadStatus = DataLoaderStatusEnum.FINISH;

    curPage = getCurPage(curChapterPagePos);
  }

  /**
   * 加载章节信息
   *
   * @param file
   * @throws Exception
   */
  protected void loadChapter(File file) throws Exception {
    List<Chapter> tmpChapters = new ArrayList<>();
    //获取文件流
    RandomAccessFile bookStream = new RandomAccessFile(file, "r");
    //寻找匹配文章标题的正则表达式，判断是否存在章节名
    boolean hasChapter = checkChapterType(bookStream);
    //加载章节
    byte[] buffer = new byte[BUFFER_SIZE];
    //获取到的块起始点，在文件中的位置
    long curOffset = 0;
    //block的个数
    int blockPos = 0;
    //读取的长度
    int length;

    //获取文件中的数据到buffer，直到没有数据为止
    while ((length = bookStream.read(buffer, 0, buffer.length)) > 0) {
      ++blockPos;
      //如果存在Chapter
      if (hasChapter) {
        //将数据转换成String
        String blockContent = new String(buffer, 0, length, mCharset.getName());
        //当前Block下使过的String的指针
        int seekPos = 0;
        //进行正则匹配
        Matcher matcher = mChapterPattern.matcher(blockContent);
        //如果存在相应章节
        while (matcher.find()) {
          //获取匹配到的字符在字符串中的起始位置
          int chapterStart = matcher.start();

          //如果 seekPos == 0 && nextChapterPos != 0 表示当前block处前面有一段内容
          //第一种情况一定是序章 第二种情况可能是上一个章节的内容
          if (seekPos == 0 && chapterStart != 0) {
            //获取当前章节的内容
            String chapterContent = blockContent.substring(seekPos, chapterStart);
            //设置指针偏移
            seekPos += chapterContent.length();

            //如果当前对整个文件的偏移位置为0的话，那么就是序章
            if (curOffset == 0) {
              //创建序章
              Chapter preChapter = new Chapter();
              preChapter.setTitle("序章");
              preChapter.setStart(0);
              preChapter.setEnd(chapterContent.getBytes(mCharset.getName()).length); //获取String的byte值,作为最终值

              //如果序章大小大于30才添加进去
              if (preChapter.getEnd() - preChapter.getStart() > 30) {
                tmpChapters.add(preChapter);
              }

              //创建当前章节
              Chapter curChapter = new Chapter();
              curChapter.setTitle(matcher.group());
              curChapter.setStart(preChapter.getEnd());
              tmpChapters.add(curChapter);
            }
            //否则就block分割之后，上一个章节的剩余内容
            else {
              //获取上一章节
              Chapter lastChapter = tmpChapters.get(tmpChapters.size() - 1);
              //将当前段落添加上一章去
              lastChapter.setEnd(lastChapter.getEnd() + chapterContent.getBytes(mCharset.getName()).length);

              //如果章节内容太小，则移除
              if (lastChapter.getEnd() - lastChapter.getStart() < 30) {
                tmpChapters.remove(lastChapter);
              }

              //创建当前章节
              Chapter curChapter = new Chapter();
              curChapter.setTitle(matcher.group());
              curChapter.setStart(lastChapter.getEnd());
              tmpChapters.add(curChapter);
            }
          } else {
            //是否存在章节
            if (tmpChapters.size() != 0) {
              //获取章节内容
              String chapterContent = blockContent.substring(seekPos, matcher.start());
              seekPos += chapterContent.length();

              //获取上一章节
              Chapter lastChapter = tmpChapters.get(tmpChapters.size() - 1);
              lastChapter.setEnd(lastChapter.getStart() + chapterContent.getBytes(mCharset.getName()).length);

              //如果章节内容太小，则移除
              if (lastChapter.getEnd() - lastChapter.getStart() < 30) {
                tmpChapters.remove(lastChapter);
              }

              //创建当前章节
              Chapter curChapter = new Chapter();
              curChapter.setTitle(matcher.group());
              curChapter.setStart(lastChapter.getEnd());
              tmpChapters.add(curChapter);
            }
            //如果章节不存在则创建章节
            else {
              Chapter curChapter = new Chapter();
              curChapter.setTitle(matcher.group());
              curChapter.setStart(0);
              tmpChapters.add(curChapter);
            }
          }
        }
      }
      //进行本地虚拟分章
      else {
        //章节在buffer的偏移量
        int chapterOffset = 0;
        //当前剩余可分配的长度
        int strLength = length;
        //分章的位置
        int chapterPos = 0;

        while (strLength > 0) {
          ++chapterPos;
          //是否长度超过一章
          if (strLength > MAX_LENGTH_WITH_NO_CHAPTER) {
            //在buffer中一章的终止点
            int end = length;
            //寻找换行符作为终止点
            for (int i = chapterOffset + MAX_LENGTH_WITH_NO_CHAPTER; i < length; ++i) {
              if (buffer[i] == Charset.BLANK) {
                end = i;
                break;
              }
            }
            Chapter chapter = new Chapter();
            chapter.setTitle("第" + blockPos + "章" + "(" + chapterPos + ")");
            chapter.setStart(curOffset + chapterOffset + 1);
            chapter.setEnd(curOffset + end);
            tmpChapters.add(chapter);
            //减去已经被分配的长度
            strLength = strLength - (end - chapterOffset);
            //设置偏移的位置
            chapterOffset = end;
          } else {
            Chapter chapter = new Chapter();
            chapter.setTitle("第" + blockPos + "章" + "(" + chapterPos + ")");
            chapter.setStart(curOffset + chapterOffset + 1);
            chapter.setEnd(curOffset + length);
            tmpChapters.add(chapter);
            strLength = 0;
          }
        }
      }

      //block的偏移点
      curOffset += length;

      if (hasChapter) {
        //设置上一章的结尾
        Chapter lastChapter = tmpChapters.get(tmpChapters.size() - 1);
        lastChapter.setEnd(curOffset);
      }

      //当添加的block太多的时候，执行GC
      if (blockPos % 15 == 0) {
        System.gc();
        System.runFinalization();
      }
    }

    chapters = tmpChapters;
    CloseUtils.closeIO(bookStream);

    System.gc();
    System.runFinalization();
  }

  /**
   * 加载页面信息
   *
   * @param chapterPos
   * @return
   */
  protected List<Page> loadPages(int chapterPos) {
    if (chapters == null) {
      throw new IllegalArgumentException("BookChapter list must not null");
    }

    Chapter chapter = chapters.get(chapterPos);
    //从文件中获取数据
    byte[] content = getChapterContent(chapter);
    ByteArrayInputStream bais = new ByteArrayInputStream(content);
    BufferedReader br = null;
    try {
      br = new BufferedReader(new InputStreamReader(bais, mCharset.getName()));
    } catch (UnsupportedEncodingException e) {
      e.printStackTrace();
    }
    return loadPages(chapter, br);
  }

  /**
   * 加载页面信息
   *
   * @param chapter
   * @param br
   * @return
   */
  protected List<Page> loadPages(Chapter chapter, BufferedReader br) {
    //生成的页面
    List<Page> pages = new ArrayList<>();
    //使用流的方式加载
    List<String> lines = new ArrayList<>();
    int rHeight = mVisibleHeight; //由于匹配到最后，会多删除行间距，所以在这里多加个行间距
    int titleLinesCount = 0;
    boolean isTitle = true; //不存在没有 Title 的情况，所以默认设置为 true。
    String paragraph = chapter.getTitle();//默认展示标题
    try {
      while (isTitle || (paragraph = br.readLine()) != null) {

        //重置段落
        if (!isTitle) {
          paragraph = paragraph.replaceAll("\\s", "");
          //如果只有换行符，那么就不执行
          if (paragraph.equals("")) continue;
          paragraph = StringUtils.toSBC("  " + paragraph + "\n");
        } else {
          //设置 title 的顶部间距
          rHeight -= mView.mTitlePara;
        }

        int wordCount = 0;
        String subStr = null;
        while (paragraph.length() > 0) {
          //当前空间，是否容得下一行文字
          if (isTitle) {
            rHeight -= mView.mTitlePaint.getTextSize();
          } else {
            rHeight -= mView.mTextPaint.getTextSize();
          }

          //一页已经填充满了，创建 TextPage
          if (rHeight < 0) {
            //创建Page
            Page page = new Page();
            page.setPosition(pages.size());
            page.setLines(new ArrayList<>(lines));
            page.setTitle(chapter.getTitle());
            page.setTitleLines(titleLinesCount);
            pages.add(page);
            //重置Lines
            lines.clear();
            rHeight = mVisibleHeight;
            titleLinesCount = 0;
            continue;
          }

          //测量一行占用的字节数
          if (isTitle) {
            wordCount = mView.mTitlePaint.breakText(paragraph, true, mVisibleWidth, null);
          } else {
            wordCount = mView.mTextPaint.breakText(paragraph, true, mVisibleWidth, null);
          }

          subStr = paragraph.substring(0, wordCount);
          if (!subStr.equals("\n")) {
            //将一行字节，存储到lines中
            lines.add(subStr);

            //设置段落间距
            if (isTitle) {
              titleLinesCount += 1;
              rHeight -= mView.mTitleInterval;
            } else {
              rHeight -= mView.mTextInterval;
            }
          }
          //裁剪
          paragraph = paragraph.substring(wordCount);
        }

        //增加段落的间距
        if (!isTitle && lines.size() != 0) {
          rHeight = rHeight - mView.mTextPara + mView.mTextInterval;
        }

        if (isTitle) {
          rHeight = rHeight - mView.mTitlePara + mView.mTitleInterval;
          isTitle = false;
        }
      }

      if (lines.size() != 0) {
        //创建Page
        Page page = new Page();
        page.setPosition(pages.size());
        page.setLines(new ArrayList<>(lines));
        page.setTitle(chapter.getTitle());
        page.setTitleLines(titleLinesCount);
        pages.add(page);
        //重置Lines
        lines.clear();
      }
    } catch (FileNotFoundException e) {
      e.printStackTrace();
    } catch (IOException e) {
      e.printStackTrace();
    } finally {
      CloseUtils.closeIO(br);
    }

    //可能出现内容为空的情况
    if (pages.size() == 0) {
      Page page = new Page();
      page.setLines(new ArrayList<>(1));
      pages.add(page);

      //curLoadStatus = DataLoaderStatusEnum.EMPTY;
    }

    //TODO 提示章节数量改变了。
    //if (mPageChangeListener != null) {
    //  mPageChangeListener.onPageCountChange(pages.size());
    //}
    return pages;
  }

  /**
   * 获取指定章节
   *
   * @param pos
   * @return
   */
  protected Page getCurPage(int pos) {
    return curPages.get(pos);
  }

  /**
   * 从文件中提取一章的内容
   *
   * @param chapter
   * @return
   */
  protected byte[] getChapterContent(Chapter chapter) {
    RandomAccessFile bookStream = null;
    try {
      bookStream = new RandomAccessFile(bookFile, "r");
      bookStream.seek(chapter.getStart());
      int extent = (int) (chapter.getEnd() - chapter.getStart());
      byte[] content = new byte[extent];
      bookStream.read(content, 0, extent);
      return content;
    } catch (FileNotFoundException e) {
      e.printStackTrace();
    } catch (IOException e) {
      e.printStackTrace();
    } finally {
      CloseUtils.closeIO(bookStream);
    }

    return new byte[0];
  }

  /**
   * 1. 检查文件中是否存在章节名
   * 2. 判断文件中使用的章节名类型的正则表达式
   *
   * @return 是否存在章节名
   */
  protected boolean checkChapterType(RandomAccessFile bookStream) throws IOException {
    //首先获取128k的数据
    byte[] buffer = new byte[BUFFER_SIZE / 4];
    int length = bookStream.read(buffer, 0, buffer.length);
    //进行章节匹配
    for (String str : CHAPTER_PATTERNS) {
      Pattern pattern = Pattern.compile(str, Pattern.MULTILINE);
      Matcher matcher = pattern.matcher(new String(buffer, 0, length, mCharset.getName()));
      //如果匹配存在，那么就表示当前章节使用这种匹配方式
      if (matcher.find()) {
        mChapterPattern = pattern;
        //重置指针位置
        bookStream.seek(0);
        return true;
      }
    }

    //重置指针位置
    bookStream.seek(0);
    return false;
  }

  /**
   * 检测当前状态是否能够进行加载章节数据
   *
   * @return
   */
  protected boolean checkStatus() {
    if (curLoadStatus == DataLoaderStatusEnum.LOADING) {
      ToastUtils.showShort("正在加载中，请稍等");
      return false;
    } else if (curLoadStatus == DataLoaderStatusEnum.ERROR) {
      //点击重试
      curLoadStatus = DataLoaderStatusEnum.LOADING;
      //mView.invalidate();
      return false;
    }
    //由于解析失败，让其退出
    return true;
  }

  /**
   * @return:获取上一个页面
   */
  protected Page getPrevPage() {
    int pos = curPage.getPosition() - 1;
    if (pos < 0) {
      return null;
    }
    //if (mPageChangeListener != null) {
    //  mPageChangeListener.onPageChange(pos);
    //}
    return curPages.get(pos);
  }

  /**
   * @return:获取下一的页面
   */
  protected Page getNextPage() {
    if (null != curPage) {
      int pos = curPage.getPosition() + 1;
      if (pos >= curPages.size()) {
        return null;
      }
      //if (mPageChangeListener != null) {
      //  mPageChangeListener.onPageChange(pos);
      //}
      return curPages.get(pos);
    }
    return new Page();
  }

  /**
   * 加载上一章
   *
   * @return true-加载成功 false-已经是第一张，无法加载
   */
  protected boolean loadPrevChapter() {
    //判断是否上一章节为空
    if (curChapterPos - 1 < 0) {
      ToastUtils.showShort("已经没有上一章了");
      return false;
    }

    //加载上一章数据
    int prevChapter = curChapterPos - 1;
    //当前章变成下一章
    nextPages = curPages;

    //判断上一章缓存是否存在，如果存在则从缓存中获取数据。
    if (mWeakPrePageList != null && mWeakPrePageList.get() != null) {
      curPages = mWeakPrePageList.get();
      mWeakPrePageList = null;
    }
    //如果不存在则加载数据
    else {
      curPages = loadPages(prevChapter);
    }

    mLastChapter = curChapterPos;
    curChapterPos = prevChapter;

    if (curPages != null) {
      curLoadStatus = DataLoaderStatusEnum.FINISH;
    }
    //如果当前章不存在，则表示在加载中
    else {
      curLoadStatus = DataLoaderStatusEnum.LOADING;
      //重置position的位置，防止正在加载的时候退出时候存储的位置为上一章的页码
      curPage.setPosition(0);
    }

    //if (mPageChangeListener != null) {
    //  mPageChangeListener.onChapterChange(mCurChapterPos);
    //}

    return true;
  }

  /**
   * 加载下一章的内容
   *
   * @return true-加载成功 false-已经是最后一章了，无法加载
   */
  protected boolean loadNextChapter() {
    //加载一章
    if (curChapterPos + 1 >= chapters.size()) {
      ToastUtils.showShort("已经没有下一章了");
      return false;
    }

    //如果存在下一章，则存储当前Page列表为上一章
    if (curPages != null) {
      mWeakPrePageList = new WeakReference<>(new ArrayList<>(curPages));
    }

    int nextChapter = curChapterPos + 1;
    //如果存在下一章预加载章节。
    if (nextPages != null) {
      curPages = nextPages;
      nextPages = null;
    } else {
      //这个PageList可能为 null，可能会造成问题。
      curPages = loadPages(nextChapter);
    }

    mLastChapter = curChapterPos;
    curChapterPos = nextChapter;

    //如果存在当前章，预加载下一章
    if (curPages != null) {
      curLoadStatus = DataLoaderStatusEnum.FINISH;
      preLoadNextChapter();
    }
    //如果当前章不存在，则表示在加载中
    else {
      curLoadStatus = DataLoaderStatusEnum.LOADING;
      //重置position的位置，防止正在加载的时候退出时候存储的位置为上一章的页码
      curPage.setPosition(0);
    }

    //if (mPageChangeListener != null) {
    //  mPageChangeListener.onChapterChange(mCurChapterPos);
    //}
    return true;
  }

  /**
   * 预加载下一章
   */
  protected void preLoadNextChapter() {
    //判断是否存在下一章
    if (curChapterPos + 1 >= chapters.size()) {
      return;
    }
    //判断下一章的文件是否存在
    int nextChapter = curChapterPos + 1;

    ThreadUtils.executeByIo(new ThreadUtils.SimpleTask<List<Page>>() {
      @Nullable
      @Override
      public List<Page> doInBackground() throws Throwable {
        return loadPages(nextChapter);
      }

      @Override
      public void onSuccess(@Nullable List<Page> result) {
        nextPages = result;
      }
    });
  }

  /**
   * 翻页接口
   */
  public interface OnPageChangeListener {
    /**
     * 当前的章节和对应的页码
     * @param chapter
     * @param page
     */
    void pageChange(int chapter, int page);
  }

  /**
   * 调用书页变更的监听器
   */
  private void invokePageChangeListener() {
    if(listener != null) {
      listener.pageChange(curChapterPos, curPage.getPosition());
    }
  }
}
